﻿using BUGCOME.Infrastructure.Extensions;
using BUGCOME.Model;
using BUGCOME.Model.File.Dto;
using Mapster;
using SqlSugar;
using SqlSugar.IOC;
using System.Data;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;

namespace BUGCOME.Repository
{
    /// <summary>
    /// 异步数据仓库类
    /// 实现基于SqlSugar的异步数据访问操作
    /// </summary>
    /// <typeparam name="T">实体类型</typeparam>
    public class BaseRepository<T> : SimpleClient<T> where T : class, new()
    {
        public ITenant itenant = null;//多租户事务

        public BaseRepository(ISqlSugarClient context = null) : base(context)
        {
            //通过特性拿到ConfigId
            var configId = typeof(T).GetCustomAttribute<TenantAttribute>()?.configId;
            if (configId != null)
            {
                Context = DbScoped.SugarScope.GetConnectionScope(configId);//根据类传入的ConfigId自动选择
            }
            else
            {
                Context = context ?? DbScoped.SugarScope.GetConnectionScope(0);//没有默认db0
            }
            itenant = DbScoped.SugarScope;//设置租户接口
        }

        #region 添加操作（异步版本）

        /// <summary>
        /// 异步插入实体
        /// </summary>
        /// <param name="t">要插入的实体</param>
        /// <param name="ignoreNull">是否忽略空值</param>
        /// <returns>受影响的行数</returns>
        public async Task<long> AddAsync(T t, bool ignoreNull = true)
        {
            return await Context.Insertable(t).IgnoreColumns(ignoreNullColumn: ignoreNull).ExecuteCommandAsync();
        }

        /// <summary>
        /// 异步批量插入实体
        /// </summary>
        /// <param name="t">实体列表</param>
        /// <returns>受影响的行数</returns>
        public async Task<long> InsertAsync(List<T> t)
        {
            return await Context.Insertable(t).ExecuteCommandAsync();
        }

        /// <summary>
        /// 异步插入实体并指定插入列
        /// </summary>
        /// <param name="parm">要插入的实体</param>
        /// <param name="iClumns">要插入的列表达式</param>
        /// <param name="ignoreNull">是否忽略空值</param>
        /// <returns>受影响的行数</returns>
        public async Task<int> InsertAsync(T parm, Expression<Func<T, object>> iClumns = null, bool ignoreNull = true)
        {
            return await Context.Insertable(parm).InsertColumns(iClumns).IgnoreColumns(ignoreNullColumn: ignoreNull).ExecuteCommandAsync();
        }

        /// <summary>
        /// 获取插入构建器（支持链式操作）
        /// </summary>
        /// <param name="t">要插入的实体</param>
        /// <returns>插入构建器</returns>
        public IInsertable<T> Insertable(T t)
        {
            return Context.Insertable(t);
        }

        #endregion 添加操作

        #region 更新操作（异步版本）

        /// <summary>
        /// 异步更新实体（根据主键）
        /// </summary>
        /// <param name="entity">要更新的实体</param>
        /// <param name="ignoreNullColumns">是否忽略空列</param>
        /// <param name="data">更新的数据（用于日志）</param>
        /// <returns>受影响的行数</returns>
        public async Task<long> UpdateAsync(T entity, bool ignoreNullColumns = false, object data = null)
        {
            return await Context.Updateable(entity).IgnoreColumns(ignoreNullColumns)
                .EnableDiffLogEventIF(data.IsNotEmpty(), data).ExecuteCommandAsync();
        }

        /// <summary>
        /// 异步更新实体指定字段（根据主键）
        /// </summary>
        /// <param name="entity">实体对象</param>
        /// <param name="expression">要更新的列表达式</param>
        /// <param name="ignoreAllNull">是否忽略所有空值</param>
        /// <returns>受影响的行数</returns>
        public async Task<long> UpdateAsync(T entity, Expression<Func<T, object>> expression, bool ignoreAllNull = false)
        {
            return await Context.Updateable(entity)
                .UpdateColumns(expression)
                .IgnoreColumns(ignoreAllNull)
                .RemoveDataCache()
                .ExecuteCommandAsync();
        }

        /// <summary>
        /// 带条件的异步更新操作
        /// </summary>
        /// <param name="entity">实体对象</param>
        /// <param name="expression">要更新的列表达式</param>
        /// <param name="where">更新条件</param>
        /// <returns>受影响的行数</returns>
        public async Task<long> UpdateAsync(T entity, Expression<Func<T, object>> expression, Expression<Func<T, bool>> where)
        {
            return await Context.Updateable(entity).UpdateColumns(expression).Where(where).ExecuteCommandAsync();
        }

        /// <summary>
        /// 表达式方式异步更新
        /// </summary>
        /// <param name="where">更新条件</param>
        /// <param name="columns">要更新的列</param>
        /// <returns>受影响的行数</returns>
        public async Task<long> UpdateAsync(Expression<Func<T, bool>> where, Expression<Func<T, T>> columns)
        {
            return await Context.Updateable<T>().SetColumns(columns).Where(where).RemoveDataCache().ExecuteCommandAsync();
        }

        #endregion 更新操作

        #region 事务操作（异步版本）

        /// <summary>
        /// 异步事务执行操作
        /// </summary>
        /// <param name="action">异步操作</param>
        /// <returns>事务结果</returns>
        public async Task<DbResult<bool>> UseTranAysnc(Func<Task> action)
        {
            try
            {
                var result = await Context.Ado.UseTranAsync(async () =>
                {
                    await action();
                    return true;
                });

                return result;
            }
            catch (Exception ex)
            {
                await Context.Ado.RollbackTranAsync();
                Console.WriteLine($"事务执行失败: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 使用指定客户端执行事务
        /// </summary>
        /// <param name="client">数据库客户端</param>
        /// <param name="action">要执行的操作</param>
        /// <returns>事务结果</returns>
        public DbResult<bool> UseTran(ISqlSugarClient client, Action action)
        {
            try
            {
                var result = client.AsTenant().UseTran(() => action());
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("事务异常" + ex.Message);
                client.AsTenant().RollbackTran();
                throw;
            }
        }

        /// <summary>
        /// 使用事务执行操作，返回是否成功
        /// </summary>
        /// <param name="action">要执行的操作</param>
        /// <returns>是否成功</returns>
        public bool UseTran2(Action action)
        {
            Console.WriteLine("---事务开始---");
            var result = Context.Ado.UseTran(() => action());
            Console.WriteLine("---事务结束---");
            return result.IsSuccess;
        }

        #endregion 事务操作

        #region 删除操作（异步版本）

        /// <summary>
        /// 获取删除构建器（支持链式操作）
        /// </summary>
        /// <returns>删除构建器</returns>
        public IDeleteable<T> Deleteable()
        {
            return Context.Deleteable<T>();
        }

        /// <summary>
        /// 异步删除指定ID的实体
        /// </summary>
        /// <param name="id">实体ID</param>
        /// <param name="title">操作标题（用于日志）</param>
        /// <returns>受影响的行数</returns>
        public async Task<long> DeleteAsync(object id, string title = "")
        {
            return await Context.Deleteable<T>(id).EnableDiffLogEventIF(title.IsNotEmpty(), title).ExecuteCommandAsync();
        }

        /// <summary>
        /// 异步删除表中所有数据
        /// </summary>
        /// <returns>受影响的行数</returns>
        public async Task<long> DeleteTableAsync()
        {
            return await Context.Deleteable<T>().ExecuteCommandAsync();
        }

        /// <summary>
        /// 异步truncate表（清空表）
        /// </summary>
        /// <returns>是否成功</returns>
        public async Task<bool> TruncateAsync()
        {
            return Context.DbMaintenance.TruncateTable<T>();
        }

        #endregion 删除操作

        #region 查询操作（异步版本）

        /// <summary>
        /// 异步判断是否存在符合条件的记录
        /// </summary>
        /// <param name="expression">查询条件</param>
        /// <returns>是否存在</returns>
        public async Task<bool> AnyAsync(Expression<Func<T, bool>> expression)
        {
            return await Context.Queryable<T>().Where(expression).AnyAsync();
        }

        /// <summary>
        /// 获取查询构建器（支持链式操作）
        /// </summary>
        /// <returns>查询构建器</returns>
        public ISugarQueryable<T> Queryable()
        {
            return Context.Queryable<T>();
        }

        /// <summary>
        /// 异步执行SQL查询并转换为列表
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="obj">参数对象</param>
        /// <returns>查询结果列表</returns>
        public async Task<List<T>> SqlQueryToListAsync(string sql, object obj = null)
        {
            return await Context.Ado.SqlQueryAsync<T>(sql, obj);
        }

        /// <summary>
        /// 异步根据主键值查询实体
        /// </summary>
        /// <param name="pkValue">主键值</param>
        /// <returns>实体对象</returns>
        public async Task<T> GetIdAsync(object pkValue)
        {
            return await Context.Queryable<T>().InSingleAsync(pkValue);
        }

        /// <summary>
        /// 异步根据条件查询分页数据
        /// </summary>
        /// <param name="where">查询条件</param>
        /// <param name="parm">分页参数</param>
        /// <returns>分页结果</returns>
        public async Task<PagedInfo<T>> GetPagesAsync(Expression<Func<T, bool>> where, PagerInfo parm)
        {
            var source = Context.Queryable<T>().Where(where);
            return await source.ToPageAsync(parm);
        }

        /// <summary>
        /// 带排序的异步分页查询
        /// </summary>
        /// <param name="where">查询条件</param>
        /// <param name="parm">分页参数</param>
        /// <param name="order">排序表达式</param>
        /// <param name="orderEnum">排序类型</param>
        /// <returns>分页结果</returns>
        public async Task<PagedInfo<T>> GetPagesAsync(Expression<Func<T, bool>> where, PagerInfo parm,
                                                      Expression<Func<T, object>> order, OrderByType orderEnum = OrderByType.Asc)
        {
            var source = Context
                .Queryable<T>()
                .Where(where)
                .OrderByIF(orderEnum == OrderByType.Asc, order, OrderByType.Asc)
                .OrderByIF(orderEnum == OrderByType.Desc, order, OrderByType.Desc);

            return await source.ToPageAsync(parm);
        }

        /// <summary>
        /// 异步多表连接分页查询（支持LeftJoin+投影）
        /// </summary>
        /// <typeparam name="TMain">主表类型（如FileBase）</typeparam>
        /// <typeparam name="TResult">最终返回的VO类型（如FileVo）</typeparam>
        /// <param name="queryBuilder">多表查询构建器（包含Join和Select逻辑）</param>
        /// <param name="where">主表查询条件</param>
        /// <param name="dto">分页参数</param>
        /// <param name="orderBy">排序字段表达式（基于TResult）</param>
        /// <param name="orderByType">排序类型</param>
        /// <returns>分页结果</returns>
        public async Task<PagedInfo<TResult>> GetPagesAsync<TMain, TResult>(
            Func<ISugarQueryable<TMain>, ISugarQueryable<TResult>> queryBuilder,
            Expression<Func<TMain, bool>> where,
            FileQueryDto dto,
            // 关键修改：将排序表达式改为基于 TResult（如FileVo）
            Expression<Func<TResult, object>> orderBy,
            OrderByType orderByType)
        {
            // 1. 初始化主表查询
            var mainQuery = Context.Queryable<TMain>().Where(where);

            // 2. 应用多表连接和投影（执行LeftJoin和Select）
            var resultQuery = queryBuilder(mainQuery);

            // 3. 排序（此时resultQuery是TResult类型，orderBy也基于TResult，类型匹配）
            resultQuery = resultQuery.OrderBy(orderBy, orderByType);

            // 4. 执行分页
            return await resultQuery.ToPageAsync(new PagerInfo
            {
                PageNum = dto.PageNum,
                PageSize = dto.PageSize
            });
        }

        /// <summary>
        /// 带自定义排序的异步分页查询
        /// </summary>
        /// <param name="where">查询条件</param>
        /// <param name="parm">分页参数</param>
        /// <param name="order">排序表达式</param>
        /// <param name="orderByType">排序类型字符串</param>
        /// <returns>分页结果</returns>
        public async Task<PagedInfo<T>> GetPagesAsync(Expression<Func<T, bool>> where, PagerInfo parm,
                                                      Expression<Func<T, object>> order, string orderByType)
        {
            return await GetPagesAsync(where, parm, order, orderByType == "desc" ? OrderByType.Desc : OrderByType.Asc);
        }

        /// <summary>
        /// 异步查询所有数据(无分页,请慎用)
        /// </summary>
        /// <param name="useCache">是否使用缓存</param>
        /// <param name="cacheSecond">缓存时间(秒)</param>
        /// <returns>实体列表</returns>
        public async Task<List<T>> GetAllAsync(bool useCache = false, int cacheSecond = 3600)
        {
            return await Context.Queryable<T>().WithCacheIF(useCache, cacheSecond).ToListAsync();
        }

        #endregion 查询操作

        #region 存储过程操作（异步版本）

        /// <summary>
        /// 异步执行存储过程并返回DataTable（不带output参数）
        /// </summary>
        /// <param name="procedureName">存储过程名称</param>
        /// <param name="parameters">参数列表</param>
        /// <returns>查询结果DataTable</returns>
        public async Task<DataTable> UseStoredProcedureToDataTableAsync(string procedureName, List<SugarParameter> parameters)
        {
            return await Context.Ado.UseStoredProcedure().GetDataTableAsync(procedureName, parameters);
        }

        /// <summary>
        /// 异步执行存储过程并返回带output参数的元组
        /// </summary>
        /// <param name="procedureName">存储过程名称</param>
        /// <param name="parameters">参数列表</param>
        /// <returns>包含DataTable和输出参数的元组</returns>
        public async Task<(DataTable, List<SugarParameter>)> UseStoredProcedureToTupleAsync(string procedureName, List<SugarParameter> parameters)
        {
            var result =  (await Context.Ado.UseStoredProcedure() .GetDataTableAsync(procedureName, parameters), parameters);
            return result;
        }

        #endregion 存储过程操作
    }

    /// <summary>
    /// 分页查询扩展（异步版本）
    /// </summary>
    public static class QueryableExtension
    {
        
        /// <summary>
        /// 异步分页查询数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">查询表单式</param>
        /// <param name="parm">分页参数</param>
        /// <returns>分页结果</returns>
        public static async Task<PagedInfo<T>> ToPageAsync<T>(this ISugarQueryable<T> source, PagerInfo parm)
        {
            var page = new PagedInfo<T>();
            RefAsync<int> total = 0;
            page.PageSize = parm.PageSize;
            page.PageIndex = parm.PageNum;

            if (parm.Sort.IsNotEmpty())
            {
                source.OrderByPropertyName(parm.Sort, parm.SortType.Contains("desc") ? OrderByType.Desc : OrderByType.Asc);
            }

            page.Result = await source.ToPageListAsync(parm.PageNum, parm.PageSize, total);
            page.TotalNum = total;
            return page;
        }

        /// <summary>
        /// 带类型转换的异步分页查询
        /// </summary>
        /// <typeparam name="T1">源类型</typeparam>
        /// <typeparam name="T2">目标类型</typeparam>
        /// <param name="source">查询表单式</param>
        /// <param name="parm">分页参数</param>
        /// <returns>分页结果</returns>
        public static async Task<PagedInfo<T2>> ToPageAsync<T1, T2>(this ISugarQueryable<T1> source, PagerInfo parm)
        {
            var page = new PagedInfo<T2>();
            RefAsync<int> total = 0;
            page.PageSize = parm.PageSize;
            page.PageIndex = parm.PageNum;

            if (parm.Sort.IsNotEmpty())
            {
                source.OrderByPropertyName(parm.Sort, parm.SortType.Contains("desc") ? OrderByType.Desc : OrderByType.Asc);
            }

            var result = await source.ToPageListAsync(parm.PageNum, parm.PageSize, total);
            page.TotalNum = total;
            page.Result = result.Adapt<List<T2>>();
            return page;
        }
    }
}